package io.scnb.lesson002.demo18;

import io.scnb.lesson002.demo18.test1.DbConfig;
import io.scnb.lesson002.demo18.test1.MainConfig1;
import io.scnb.lesson002.demo18.test2.DbUtil;
import io.scnb.lesson002.demo18.test2.MailConfig;
import io.scnb.lesson002.demo18.test2.MainConfig2;
import io.scnb.lesson002.demo18.test3.BeanMyScope;
import io.scnb.lesson002.demo18.test3.MainConfig3;
import io.scnb.lesson002.demo18.test3.User;
import io.scnb.lesson002.demo18.test4.BeanRefreshScope;
import io.scnb.lesson002.demo18.test4.MailService;
import io.scnb.lesson002.demo18.test4.MainConfig4;
import io.scnb.lesson002.demo18.test4.RefreshConfigUtil;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.MapPropertySource;

import java.util.Map;
import java.util.concurrent.TimeUnit;

public class ValueTest {
    
    @Test
    public void test1() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(MainConfig1.class);
        context.refresh();

        DbConfig dbConfig = context.getBean(DbConfig.class);
        System.out.println(dbConfig);
    }
    
    @Test
    public void test2() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

        Map<String, Object> mailInfoMap = DbUtil.getMailInfoMap();
        
        // 将从db中获取的邮件配置信息放入到MapPropertySource中
        MapPropertySource mailPropertySource = new MapPropertySource("mail", mailInfoMap);
        
        // 将mailPropertySource放入到Environment中的PropertySource列表的第一个，让其优先级最高
        context.getEnvironment().getPropertySources().addFirst(mailPropertySource);
        
        context.register(MainConfig2.class);
        context.refresh();

        MailConfig mailConfig = context.getBean(MailConfig.class);
        System.out.println(mailConfig);
    }
    
    @Test
    public void test3() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        //将自定义作用域注册到spring容器中
        context.getBeanFactory().registerScope(BeanMyScope.SCOPE_MY, new BeanMyScope());//@1
        context.register(MainConfig3.class);
        context.refresh();
        System.out.println("从容器中获取User对象");
        User user = context.getBean(User.class); //@2
        System.out.println("user对象的class为：" + user.getClass()); //@3
        System.out.println("多次调用user的getUsername感受一下效果\n");
        for (int i = 1; i <= 3; i++) {
            System.out.println(String.format("********\n第%d次开始调用getUsername", i));
            System.out.println(user.getUsername());
            System.out.println(String.format("第%d次调用getUsername结束\n********\n", i));
        }
    }
    
    @Test
    public void test4() throws InterruptedException {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.getBeanFactory().registerScope(BeanRefreshScope.SCOPE_REFRESH, BeanRefreshScope.getInstance());
        context.register(MainConfig4.class);
        //刷新mail的配置到Environment
        RefreshConfigUtil.refreshMailPropertySource(context);
        context.refresh();
        MailService mailService = context.getBean(MailService.class);
        System.out.println("配置未更新的情况下,输出3次");
        for (int i = 0; i < 3; i++) { //@1
            System.out.println(mailService);
            TimeUnit.MILLISECONDS.sleep(200);
        }
        System.out.println("模拟3次更新配置效果");
        for (int i = 0; i < 3; i++) { //@2
            RefreshConfigUtil.updateDbConfig(context); //@3
            // 在打印mailService的时候，会调用mailConfig这个bean的toString方法，又因为MailConfig标注了@RefreshScope注解
            // 所以在调用mailConfig的toString方法时，相当于调用MailConfig代理对象的toString方法，这又会调用自定义的作用域类
            // 中的get方法来重新获取这个bean对象，从新获取bean对象的时候，会从context里拿mail.username的值来注入到username字段中
            // 因此达到了自动刷新@Value标注的字段值得效果
            System.out.println(mailService);
            TimeUnit.MILLISECONDS.sleep(200);
        }
    }
}
